//
//  SHLoadingView.m
//  Dejal Open Source
//
//  Created by David Sinclair on 2009-07-26.
//  Copyright (c) 2009-2012 Dejal Systems, LLC. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met:
//
//  - Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//
//  - Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
//  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
//  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
//  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//  Credit: inspired by Matt Gallagher's LoadingView blog post:
//  http://cocoawithlove.com/2009/04/showing-message-over-iphone-keyboard.html
//


#import "SHLoadingView.h"
#import <QuartzCore/QuartzCore.h>
#import "SHToastView.h"

@interface UILabel (SHLoadingView_RatLabel)

- (CGRect)adjustLabelFrameHeight;
- (CGRect)adjustLabelFrameHeightWithWidth:(CGFloat)width;
- (CGRect)adjustLabelFrameRect;
@end
//
//  RatLabel+UILabel.m
//  RatObjcSDK
//
//  Created by shaofeng on 14/12/18.
//  Copyright (c) 2014年 shaofeng. All rights reserved.
//
@implementation UILabel (SHLoadingView_RatLabel)

- (CGRect)adjustLabelFrameHeight
{
    return [self adjustLabelFrameHeightWithWidth:0.0];
}

- (CGRect)adjustLabelFrameHeightWithWidth:(CGFloat)width
{
    if ([self.text isEqualToString:@""])
    {
        return CGRectMake(self.frame.origin.x, self.frame.origin.y, width, 0);
    }
    
    CGFloat labelWidth = width;
    if (labelWidth<=0.0)
    {
        labelWidth = self.frame.size.width;
    }
    CGFloat height;
    
    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1)
    {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        CGSize size = [self.text sizeWithFont:self.font
                            constrainedToSize:CGSizeMake(labelWidth, FLT_MAX)
                                lineBreakMode:NSLineBreakByWordWrapping];
        
        height = size.height;
#pragma clang diagnostic pop
    }
    else
    {
        NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
        context.minimumScaleFactor = 1.0;
        CGRect bounds = [self.text boundingRectWithSize:CGSizeMake(labelWidth, FLT_MAX)
                                                options:NSStringDrawingUsesLineFragmentOrigin
                                             attributes:@{NSFontAttributeName:self.font}
                                                context:context];
        height = bounds.size.height;
    }
    
    return CGRectMake(self.frame.origin.x, self.frame.origin.y, labelWidth, height);
}

- (CGRect)adjustLabelFrameRect
{
    if ([self.text isEqualToString:@""])
    {
        return CGRectMake(self.frame.origin.x, self.frame.origin.y, 0.0, 0);
    }
    
    CGFloat labelWidth = 0.0;
    if (labelWidth<=0.0)
    {
        labelWidth = self.frame.size.width;
    }
    CGFloat height;
    
    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1)
    {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        CGSize size = [self.text sizeWithFont:self.font
                            constrainedToSize:CGSizeMake(labelWidth, FLT_MAX)
                                lineBreakMode:self.lineBreakMode];
        
        height = size.height;
#pragma clang diagnostic pop
    }
    else
    {
        NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
        context.minimumScaleFactor = 1.0;
        CGRect bounds = [self.text boundingRectWithSize:CGSizeMake(labelWidth, FLT_MAX)
                                                options:NSStringDrawingUsesLineFragmentOrigin
                                             attributes:@{NSFontAttributeName:self.font}
                                                context:context];
        height = bounds.size.height;
    }
    
    return CGRectMake(self.frame.origin.x, self.frame.origin.y, labelWidth, height);
}

@end


#pragma mark -

@interface SHLoadingView ()

@property (nonatomic, weak) UIView *originalView;
@property (nonatomic, strong) UIView *borderView;
@property (nonatomic, strong) UIActivityIndicatorView *activityIndicator;
@property (nonatomic , strong) UIView *activityBgView;

@end


// ----------------------------------------------------------------------------------------
// MARK: -
// ----------------------------------------------------------------------------------------


@implementation SHLoadingView

@synthesize originalView, borderView, activityWhaleSwimmingView, activityIndicator, activityLabel;

static SHLoadingView *gloableLoadingView = nil;
static float animateTime = 0.15;
static float animateRemoveTime = 0.5;

/*
 currentActivityView
 
 Returns the currently displayed activity view, or nil if there isn't one.
 
 Written by DJS 2009-07.
 */

+ (SHLoadingView *)currentActivityView;
{
    return gloableLoadingView;
}

+ (SHLoadingView *)loadingViewForView:(UIView *)addToView
{
    return [self loadingViewForView:addToView withLabel:NSLocalizedString(@"Loading...", @"Default DejalActivtyView label text")];
}

+ (SHLoadingView *)loadingViewForView:(UIView *)addToView withLabel:(NSString *)labelText
{
    if (gloableLoadingView)
        [self removeView];
    
    // Remember the new view (so this is a singleton):
    gloableLoadingView = [[self alloc] initWhaleSwimmingForView:addToView withLabel:labelText];
    
    return gloableLoadingView;
}

- (SHLoadingView *)initWhaleSwimmingForView:(UIView *)addToView withLabel:(NSString *)labelText
{
    if (!(self = [super initWithFrame:CGRectZero]))
        return nil;
    
    // Allow subclasses to change the view to which to add the activity view (e.g. to cover the keyboard):
    self.originalView = addToView;
    addToView = [self viewForView:addToView];
    
    /**
     *  暂时去掉背景颜色
     */
    [self setupBackground];
    self.borderView = [self makeBorderView];
//    self.activityWhaleSwimmingView = [self makeWhaleSwimming];
    self.activityLabel = [self makeActivityLabelWithText:labelText];
    self.activityBgView = [UIView new];
    self.activityBgView.layer.cornerRadius = 5;
    self.activityBgView.layer.masksToBounds = true;
    self.activityBgView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
    self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    
    // Assemble the subviews:
    [addToView addSubview:self];
    [self addSubview:self.borderView];
    [self.borderView addSubview:self.activityBgView];
    [self.activityBgView addSubview:self.activityIndicator];
//    [self.borderView addSubview:self.activityWhaleSwimmingView];
    [self.activityBgView addSubview:self.activityLabel];
    
    [self.activityIndicator startAnimating];
    [self animateShow];
    
    return self;
}

- (void)dealloc;
{
    if ([gloableLoadingView isEqual:self])
        gloableLoadingView = nil;
}

/*
 removeView
 
 Immediately removes and releases the view without any animation.
 
 Written by DJS 2009-07.
 Changed by DJS 2009-09 to disable the network activity indicator if it was shown by this view.
 */

+ (float)removeAnimateTime
{
    return animateTime + animateRemoveTime;
}

+ (void)removeView;
{
    if (!gloableLoadingView)
        return;
    SHLoadingView * temp = gloableLoadingView;
    gloableLoadingView = nil;
    [UIView animateWithDuration:animateRemoveTime animations:^{
        temp.alpha = 0.0;
    } completion:^(BOOL finished) {
        [temp removeFromSuperview];
    }];
}

/*
 viewForView:
 
 Returns the view to which to add the activity view.  By default returns the same view.  Subclasses may override this to change the view.
 
 Written by DJS 2009-07.
 */

- (UIView *)viewForView:(UIView *)view;
{
    return view;
}

/*
 enclosingFrame
 
 Returns the frame to use for the activity view.  Defaults to the superview's bounds.  Subclasses may override this to use something different, if desired.
 
 Written by DJS 2009-07.
 */

- (CGRect)enclosingFrame;
{
    return self.superview.bounds;
}

/*
 setupBackground
 
 Configure the background of the activity view.
 
 Written by DJS 2009-07.
 */

- (void)setupBackground;
{
    self.opaque = NO;
    self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}

/*
 makeBorderView
 
 Returns a new view to contain the activity indicator and label.  By default this view is transparent.  Subclasses may override this method, optionally calling super, to use a different or customized view.
 
 Written by DJS 2009-07.
 Changed by DJS 2011-11 to simplify and make it easier to override.
 */

- (UIView *)makeBorderView;
{
    UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
    
    view.opaque = NO;
    view.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
    
    return view;
}

- (UIImageView *)makeWhaleSwimming
{
    NSMutableArray *loadingImgsArray = [NSMutableArray array];
    for (int i = 0; i< 79; i++) {
        NSString *fileName = [NSString stringWithFormat:@"common_loading_%d",i];
        [loadingImgsArray addObject:[UIImage imageNamed:fileName]];
    }
    
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, 60)];
    imageView.contentMode = UIViewContentModeCenter;
    imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    imageView.animationImages = loadingImgsArray;
    imageView.animationDuration = 3.0;
    [imageView startAnimating];
    
    return imageView;
}

/*
 makeActivityLabelWithText:
 
 Returns a new activity label.  Subclasses may override this method, optionally calling super, to use a different or customized view.
 
 Written by DJS 2009-07.
 Changed by DJS 2011-11 to simplify and make it easier to override.
 */

- (UILabel *)makeActivityLabelWithText:(NSString *)labelText;
{
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
    
    label.font = [UIFont systemFontOfSize:11.0];
    label.textAlignment = NSTextAlignmentCenter;
    label.textColor = [UIColor whiteColor];
    label.backgroundColor = [UIColor clearColor];
//    label.shadowColor = [UIColor whiteColor];
//    label.shadowOffset = CGSizeMake(0.0, 1.0);
    label.numberOfLines = 0;
    label.text = labelText;
    return label;
}

/*
 layoutSubviews
 
 Positions and sizes the various views that make up the activity view, including after rotation.
 
 Written by DJS 2009-07.
 */

- (void)layoutSubviews;
{
    self.frame = [self enclosingFrame];
    
    // If we're animating a transform, don't lay out now, as can't use the frame property when transforming:
    if (!CGAffineTransformIsIdentity(self.borderView.transform))
        return;
    
    float borderViewWidth = 100.0f;
    float labelLeft = 5.0f;
    float activityIndicatorTop = 10.0f;
    float labelTop = 10.0f;
    
    CGRect labelFrame = CGRectMake(labelLeft, 0, borderViewWidth - labelLeft * 2, 0);
    self.activityLabel.frame = labelFrame;
    CGRect rect = [self.activityLabel adjustLabelFrameHeight];
    if (rect.size.height <= 0) {
        labelTop = 0;
    }
    // Calculate the size and position for the border view: with the indicator vertically above the label, and centered in the receiver:
    CGRect borderFrame = CGRectZero;
    
    borderFrame.size.width = borderViewWidth;
    borderFrame.size.height = self.activityIndicator.frame.size.height+ activityIndicatorTop + rect.size.height + labelTop + activityIndicatorTop;
    
    borderFrame.origin.x = floor(0.5 * (self.frame.size.width - borderFrame.size.width));
    borderFrame.origin.y = floor(0.5 * (self.frame.size.height - borderFrame.size.height))-32;
    self.borderView.frame = borderFrame;
    
    self.activityBgView.frame = CGRectMake(0, 0, MAX(borderViewWidth, rect.size.width), borderViewWidth + labelTop + rect.size.height);
    self.activityIndicator.frame = CGRectMake(0, 0, MAX(borderViewWidth, rect.size.width), borderViewWidth + labelTop + rect.size.height);
    self.activityLabel.frame = CGRectMake(0, borderViewWidth, MAX(borderViewWidth, rect.size.width), rect.size.height);
//    CGRect indicatorFrame = self.activityWhaleSwimmingView.frame;
//    indicatorFrame.origin.x = 0.5 * (borderFrame.size.width - indicatorFrame.size.width);
//    indicatorFrame.origin.y = activityIndicatorTop;
//    self.activityWhaleSwimmingView.frame = indicatorFrame;
//    self.activityLabel.frame = CGRectMake(labelLeft, self.activityWhaleSwimmingView.frame.size.height + labelTop, labelFrame.size.width, rect.size.height);
}

/*
 animateShow
 
 Animates the view into visibility.  Does nothing for the simple activity view.
 
 Written by DJS 2009-07.
 */

- (void)animateShow;
{
    // Does nothing by default
}

#pragma mark - 四维兼容
+ (void)show:(NSString *)text inView:(UIView *)view {
    [SHLoadingView loadingViewForView:view withLabel:text];
}

+ (void)showForceWithText:(NSString *)text inView:(UIView *)view {
    [SHLoadingView loadingViewForView:view withLabel:text];
}

+ (void)close {
    [SHLoadingView removeView];
}

+ (void)closeWithText:(BOOL)success textForView:(NSString *)text {
    if (gloableLoadingView) {
        [self removeView];
    }
    [SHToastView showWithText:text];
}

+ (void)closeWithText:(BOOL)success textForView:(NSString *)text completion:(void (^)(void))completion {
    // TODO: 目前暂不支持成功后换图片
    //    [self removeView];
    if (gloableLoadingView) {
        [self removeView];
    }
    
    [SHToastView showWithText:text];
    if (completion) {
        completion();
    }

}


@end

// ----------------------------------------------------------------------------------------
// MARK: -
// ----------------------------------------------------------------------------------------


@implementation AWDejalBezelActivityView

/*
 viewForView:
 
 Returns the view to which to add the activity view.  For the bezel style, if there is a keyboard displayed, the view is changed to the keyboard's superview.
 
 Written by DJS 2009-07.
 */

- (UIView *)viewForView:(UIView *)view;
{
    UIView *keyboardView = [[UIApplication sharedApplication] keyboardView];
    
    if (keyboardView)
        view = keyboardView.superview;
    
    return view;
}

/*
 enclosingFrame
 
 Returns the frame to use for the activity view.  For the bezel style, if there is a keyboard displayed, the frame is changed to cover the keyboard too.
 
 Written by DJS 2009-07.
 */

- (CGRect)enclosingFrame;
{
    CGRect frame = [super enclosingFrame];
    
    if (self.superview != self.originalView)
        frame = [self.originalView convertRect:self.originalView.bounds toView:self.superview];
    
    return frame;
}

/*
 setupBackground
 
 Configure the background of the activity view.
 
 Written by DJS 2009-07.
 */

- (void)setupBackground;
{
    [super setupBackground];
}

/*
 makeBorderView
 
 Returns a new view to contain the activity indicator and label.  The bezel style has a semi-transparent rounded rectangle.
 
 Written by DJS 2009-07.
 Changed by DJS 2011-11 to simplify and make it easier to override.
 */

- (UIView *)makeBorderView;
{
    UIView *view = [super makeBorderView];
    
    view.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.4];
    view.layer.cornerRadius = 10.0;
    
    return view;
}


/*
 makeActivityLabelWithText:
 
 Returns a new activity label.  The bezel style uses centered white text.
 
 Written by DJS 2009-07.
 Changed by Suleman Sidat 2011-07 to support a multi-line label.
 Changed by DJS 2011-11 to simplify and make it easier to override.
 */

- (UILabel *)makeActivityLabelWithText:(NSString *)labelText;
{
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
    
    label.font = [UIFont boldSystemFontOfSize:11.0];
    label.textAlignment = NSTextAlignmentCenter;
    label.textColor = [UIColor whiteColor];
    label.backgroundColor = [UIColor clearColor];
    label.numberOfLines = 0;
    label.lineBreakMode = NSLineBreakByWordWrapping;
    label.text = labelText;
    
    return label;
}

/*
 layoutSubviews
 
 Positions and sizes the various views that make up the activity view, including after rotation.
 
 Written by DJS 2009-07.
 Changed by Suleman Sidat 2011-07 to support a multi-line label.
 */

- (void)layoutSubviews;
{
    // If we're animating a transform, don't lay out now, as can't use the frame property when transforming:
    if (!CGAffineTransformIsIdentity(self.borderView.transform))
        return;
    
    self.frame = [self enclosingFrame];
    
    float borderViewWidth = 150.0f;
    float labelLeft = 5.0f;
    float activityIndicatorTop = 10.0f;
    float labelTop = 10.0f;
    
    CGRect labelFrame = CGRectMake(labelLeft, 0, borderViewWidth - labelLeft * 2, 0);
    self.activityLabel.frame = labelFrame;
    CGRect rect = [self.activityLabel adjustLabelFrameHeight];
    
    // Calculate the size and position for the border view: with the indicator vertically above the label, and centered in the receiver:
    CGRect borderFrame = CGRectZero;
    
    
    borderFrame.size.width = borderViewWidth;
    borderFrame.size.height = self.activityWhaleSwimmingView.frame.size.height+ activityIndicatorTop + rect.size.height + labelTop + activityIndicatorTop;
    
    borderFrame.origin.x = floor(0.5 * (self.frame.size.width - borderFrame.size.width));
    borderFrame.origin.y = floor(0.5 * (self.frame.size.height - borderFrame.size.height))-32;
    self.borderView.frame = borderFrame;
    
    CGRect indicatorFrame = self.activityWhaleSwimmingView.frame;
    indicatorFrame.origin.x = 0.5 * (borderFrame.size.width - indicatorFrame.size.width);
    indicatorFrame.origin.y = activityIndicatorTop;
    self.activityWhaleSwimmingView.frame = indicatorFrame;
    self.activityLabel.frame = CGRectMake(labelLeft, self.activityWhaleSwimmingView.frame.size.height + labelTop, labelFrame.size.width, rect.size.height);
}

/*
 animateShow
 
 Animates the view into visibility.  For the bezel style, fades in the background and zooms the bezel down from a large size.
 
 Written by DJS 2009-07.
 */

- (void)animateShow;
{
    self.alpha = 0.0;
    self.borderView.transform = CGAffineTransformMakeScale(1.5, 1.5);
    
    [UIView beginAnimations:nil context:nil];
    //    [UIView setAnimationDuration:5.0];            // Uncomment to see the animation in slow motion
    
    self.borderView.transform = CGAffineTransformIdentity;
    self.alpha = 1.0;
    
    [UIView commitAnimations];
}

- (void)removeAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context;
{
    [[self class] removeView];
}

/*
 removeViewAnimated:
 
 Animates the view out from the superview and releases it, or simply removes and releases it immediately if not animating.
 
 Written by DJS 2009-07.
 */

+ (void)removeViewAnimated:(BOOL)animated;
{
    UIView *view = [self currentActivityView];
    if (view) {
        if (!gloableLoadingView)
            return;
        
        /**
         *  暂时去掉遮罩动画, by 李魁峰
         */
        //        if (animated)
        //            [SHLoadingView animateRemoveTag:tag];
        //        else
        [[self class] removeView];
    }
}

@end

@implementation UIApplication (KeyboardView)

//  keyboardView
//
//  Copyright Matt Gallagher 2009. All rights reserved.
//
//  Permission is given to use this source code file, free of charge, in any
//  project, commercial or otherwise, entirely at your risk, with the condition
//  that any redistribution (in part or whole) of source code must retain
//  this copyright and permission notice. Attribution in compiled projects is
//  appreciated but not required.

- (UIView *)keyboardView;
{
    NSArray *windows = [self windows];
    for (UIWindow *window in [windows reverseObjectEnumerator])
    {
        for (UIView *view in [window subviews])
        {
            // UIPeripheralHostView is used from iOS 4.0, UIKeyboard was used in previous versions:
            if (!strcmp(object_getClassName(view), "UIPeripheralHostView") || !strcmp(object_getClassName(view), "UIKeyboard"))
            {
                return view;
            }
        }
    }
    
    return nil;
}
@end
